package com.hm.base.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.hm.base.auto.su.BeanUtil;
import com.hm.base.auto.su.R.RedisKey;
import com.hm.base.domain.DataAuth;
import com.hm.base.domain.Role;
import com.hm.base.domain.RoleDataAuth;
import com.hm.base.mapper.DataAuthMapper;
import com.hm.base.mapper.RoleDataAuthMapper;
import com.hm.base.mapper.RoleMapper;
import com.hm.base.vo.DataAuthSupportVo;
import com.hm.base.vo.DataAuthVo;
import com.hm.base.vo.LoginSubscriberVo;
import com.hm.base.vo.SystemConfigDictVo;
import com.hm.common.def.DataStatusDef;
import com.hm.common.def.WhetherDef;
import com.hm.common.exception.ErrorCode;
import com.hm.common.exception.ServiceException;
import com.hm.common.su.bean.PageInfo;
import com.hm.common.su.bean.PageInfo.PageParam;
import com.hm.common.util.CollectionUtil;
import com.hm.common.util.CommonUtil;
import com.hm.common.util.DateUtil;
import com.hm.common.util.StringUtil;

import lombok.extern.slf4j.Slf4j;

/**
 * @author shishun.wang
 * @date 下午4:58:25 2017年6月2日
 * @version 1.0
 * @describe 数据权限
 */
@Slf4j
@Service
@Transactional
public class DataAuthServiceImpl implements DataAuthService {

	@Autowired
	private RoleMapper roleMapper;

	@Autowired
	private DataAuthMapper dataAuthMapper;

	@Autowired
	private RoleDataAuthMapper roleDataAuthMapper;

	@Autowired
	private AuthorizationService authorizationService;

	@Autowired
	private RedisTemplate<String, String> redisTemplate;

	@Autowired
	private SystemConfigDictService systemConfigDictService;

	@Override
	public List<String> getDataAuthCodesByUserId(Long subscriberId) {
		if (CommonUtil.isEmpty(subscriberId)) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}

		List<String> vos = new ArrayList<String>();
		LoginSubscriberVo subscriberVo = authorizationService.loadLoginToken(subscriberId);
		if (CommonUtil.isEmpty(subscriberVo)) {
			throw ServiceException.warning(ErrorCode.DATA_NOT_NULL);
		}
		subscriberVo.getRoles().forEach(roleId -> {
			String key = RedisKey.SYSTEM_DATA_AUTH_PREFIX + ":" + roleId;

			String dataAuthCache = redisTemplate.opsForValue().get(key);
			if (StringUtil.isBlankOrNull(dataAuthCache)) {
				return;
			}

			List<String> authDatas = JSON.parseArray(dataAuthCache, String.class);
			if (CommonUtil.isEmpty(authDatas)) {
				return;
			}

			vos.addAll(authDatas);
		});

		return CollectionUtil.distinct(vos);
	}

	@Override
	public List<DataAuthSupportVo> getDataAuthsByRoleId(Long roleId, String platform) {
		if (CommonUtil.isAnyEmpty(roleId, platform)) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}

		List<SystemConfigDictVo> dicts = systemConfigDictService.loadSystemConfigDictByDictType(platform);
		if (CommonUtil.isEmpty(dicts)) {
			return new ArrayList<DataAuthSupportVo>(0);
		}

		return dicts.parallelStream().map(dict -> {
			DataAuthSupportVo vo = new DataAuthSupportVo();
			vo.setModuleId(dict.getCode());
			vo.setModuleName(dict.getName());

			DataAuth dataAuth = new DataAuth();
			dataAuth.setModuleId(dict.getCode());

			List<DataAuth> dataAuths = dataAuthMapper.select(dataAuth);
			if (CommonUtil.isEmpty(dataAuths)) {
				return vo;
			}

			vo.setDataAuths(dataAuths.parallelStream().map(auth -> {
				DataAuthVo dataAuthVo = new DataAuthVo();
				BeanUtil.copyProperties(auth, dataAuthVo);

				RoleDataAuth roleDataAuth = new RoleDataAuth();
				roleDataAuth.setRoleId(roleId);
				roleDataAuth.setDataAuthId(auth.getId());

				dataAuthVo.setHasRole(roleDataAuthMapper.selectCount(roleDataAuth) > 0);

				return dataAuthVo;
			}).collect(Collectors.toList()));

			return vo;
		}).collect(Collectors.toList());
	}

	@Override
	public void settingDataAuthsByRoleId(Long roleId, List<Long> dataAuthIds, String platform) {
		if (CommonUtil.isAnyEmpty(roleId, platform)) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}

		Role role = roleMapper.selectByPrimaryKey(roleId);
		if (CommonUtil.isEmpty(role)) {
			throw ServiceException.warning(ErrorCode.DATA_NOT_FOUND, "角色");
		}

		if (WhetherDef.trance(role.getSystemDefault()) == WhetherDef.YES) {
			throw ServiceException.warning(ErrorCode.NO_DATA_ACCESS);
		}

		Map<String, Object> params = new HashMap<String, Object>();
		{
			params.put("platform", platform);
			params.put("roleId", roleId);
		}
		List<Map<String,Object>> dataAuths = roleDataAuthMapper.loadRoleDataAuths(params);
		if(CommonUtil.isNotEmpty(dataAuths)) {
			dataAuths.forEach(dAuth ->{
				log.info("删除角色数据权限{}",dAuth.get("id"));
				RoleDataAuth record = new RoleDataAuth();
				record.setId(Long.parseLong(dAuth.get("id")+""));
				roleDataAuthMapper.delete(record);
			});
		}
		
		if (CommonUtil.isNotEmpty(dataAuthIds)) {
			roleDataAuthMapper.insertList(dataAuthIds.parallelStream().map(dataAuthId -> {
				RoleDataAuth item = new RoleDataAuth();
				item.setRoleId(roleId);
				item.setDataAuthId(dataAuthId);

				return item;
			}).collect(Collectors.toList()));
		}
		this.refreshDataAuthsByRoleId(roleId);
	}

	@Override
	public void refreshDataAuthsByRoleId(Long roleId) {
		if (CommonUtil.isEmpty(roleId)) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}

		Role role = roleMapper.selectByPrimaryKey(roleId);
		if (CommonUtil.isEmpty(role)) {
			throw ServiceException.warning(ErrorCode.DATA_NOT_FOUND);
		}

		if (WhetherDef.trance(role.getSystemDefault()) == WhetherDef.YES) {
			throw ServiceException.warning(ErrorCode.NO_DATA_ACCESS);
		}

		Map<String, Object> param = new HashMap<String, Object>();
		{
			param.put("roleId", roleId);
		}
		List<String> dataAuths = dataAuthMapper.getRoleDataAuths(param);
		if (CommonUtil.isEmpty(dataAuths)) {
			return;
		}

		String key = RedisKey.SYSTEM_DATA_AUTH_PREFIX + ":" + roleId;
		log.info("刷新角色{}数据权限缓存key[{}],数据值{}", roleId, key, dataAuths.toString());
		redisTemplate.opsForValue().set(key, JSON.toJSONString(dataAuths));
	}

	@Override
	public void addDataAuth(DataAuthVo vo) {
		if (CommonUtil.isAnyEmpty(vo.getAuthCode(), vo.getName(), vo.getSort(), vo.getModuleId())) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}

		DataAuth query = new DataAuth();
		{
			query.setAuthCode(vo.getAuthCode());
		}

		if (CommonUtil.isNotEmpty(dataAuthMapper.selectOne(query))) {
			throw ServiceException.warning(ErrorCode.DATA_EXISTING);
		}

		DataAuth dataAuth = new DataAuth();
		BeanUtil.copyProperties(vo, dataAuth);
		dataAuth.setId(null);
		dataAuth.setCreateTime(new Date());
		dataAuth.setStatus(DataStatusDef.ENABLE.name());
		dataAuth.setSystemDefault(WhetherDef.NO.name());

		dataAuthMapper.insert(dataAuth);

		// 刷新超级管理员数据权限
		{
			RoleDataAuth roleDataAuth = new RoleDataAuth();
			{
				roleDataAuth.setRoleId(1l);
				roleDataAuth.setDataAuthId(dataAuthMapper.selectOne(query).getId());
			}
			roleDataAuthMapper.insert(roleDataAuth);

			Map<String, Object> param = new HashMap<String, Object>();
			{
				param.put("roleId", 1l);
			}
			List<String> dataAuths = dataAuthMapper.getRoleDataAuths(param);
			if (CommonUtil.isEmpty(dataAuths)) {
				return;
			}

			String key = RedisKey.SYSTEM_DATA_AUTH_PREFIX + ":" + 1;
			log.info("刷新角色{}数据权限缓存key[{}],数据值{}", 1l, key, dataAuths.toString());
			redisTemplate.opsForValue().set(key, JSON.toJSONString(dataAuths));
		}
	}

	@Override
	public void updateDataAuth(DataAuthVo vo) {
		if (CommonUtil.isAnyEmpty(vo.getId(), vo.getAuthCode(), vo.getName(), vo.getSort())) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}
		DataAuth query = new DataAuth();
		{
			query.setAuthCode(vo.getAuthCode());
		}
		DataAuth queryDataAuth = dataAuthMapper.selectOne(query);
		if (CommonUtil.isNotEmpty(queryDataAuth) && queryDataAuth.getId().longValue() != vo.getId().longValue()) {
			throw ServiceException.warning(ErrorCode.DATA_EXISTING);
		}

		DataAuth dataAuth = dataAuthMapper.selectByPrimaryKey(vo.getId());
		if (CommonUtil.isEmpty(dataAuth)) {
			throw ServiceException.warning(ErrorCode.DATA_NOT_FOUND);
		}

		if (WhetherDef.trance(dataAuth.getSystemDefault()) == WhetherDef.YES) {
			throw ServiceException.warning(ErrorCode.NO_DATA_ACCESS);
		}

		dataAuth.setName(vo.getName());
		dataAuth.setNote(vo.getNote());
		dataAuth.setAuthCode(vo.getAuthCode());
		dataAuth.setSort(vo.getSort());
		dataAuthMapper.updateByPrimaryKey(dataAuth);

		// 刷新用户数据权限
		authorizationService.refreshSystemRoleDataAuth();
	}

	@Override
	public void deleteDataAuth(List<Long> dataAuthIds) {
		if (CommonUtil.isEmpty(dataAuthIds)) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}

		dataAuthIds.forEach(dataAuthId -> {
			DataAuth dataAuth = dataAuthMapper.selectByPrimaryKey(dataAuthId);
			if (CommonUtil.isEmpty(dataAuth)) {
				return;
			}

			if (WhetherDef.trance(dataAuth.getSystemDefault()) == WhetherDef.NO) {
				dataAuthMapper.delete(dataAuth);
			}
		});

		// 刷新用户数据权限
		authorizationService.refreshSystemRoleDataAuth();
	}

	@Override
	public DataAuthVo getDataAuth(Long dataAuthId) {
		if (CommonUtil.isEmpty(dataAuthId)) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}

		DataAuth dataAuth = dataAuthMapper.selectByPrimaryKey(dataAuthId);
		if (CommonUtil.isEmpty(dataAuth)) {
			throw ServiceException.warning(ErrorCode.DATA_NOT_FOUND);
		}

		DataAuthVo vo = new DataAuthVo();
		BeanUtil.copyProperties(dataAuth, vo);

		return vo;
	}

	@Override
	public PageInfo<DataAuthVo> query(PageParam pageParam, String name, String module, String authCode) {
		Page<DataAuth> page = PageHelper.startPage(pageParam.getPage(), pageParam.getSize(), true);
		DataAuth query = new DataAuth();
		if (StringUtil.isNotBlank(name)) {
			query.setName(name);
		}

		if (StringUtil.isNotBlank(module)) {
			query.setModuleId(module);
		}

		if (StringUtil.isNotBlank(authCode)) {
			query.setAuthCode(authCode);
		}
		dataAuthMapper.query(query);

		if (CommonUtil.isEmpty(page.getResult())) {
			return new PageInfo<DataAuthVo>(new ArrayList<DataAuthVo>(0), page.getPages(), page.getTotal());
		}

		return new PageInfo<DataAuthVo>(page.getResult().parallelStream().map(item -> {
			DataAuthVo vo = new DataAuthVo();
			BeanUtil.copyProperties(item, vo);
			vo.setCreateTime(DateUtil.data2long(item.getCreateTime()));
			vo.setSystemCfg(WhetherDef.trance(item.getSystemDefault()) == WhetherDef.YES);

			return vo;
		}).collect(Collectors.toList()), page.getPages(), page.getTotal());
	}
}
